Welcome

Uncaught Exception Handling in Java Server Faces

First comes a little flashback on how we can deal with uncaught exceptions in web applications. As you probably know, there exists a general exception/error trapping mechanism for servlet/jsp based web applications. We simply add error-page definitions in web.xml file for uncaught exceptions or http status codes to show users custom error pages instead of bare exception stack traces or http status code pages. This mechanism applies for all jsp pages. If we want to override those definitions, we can always use errorPage page directive in jsp pages to forward request in case there happens an uncaught exception during request processing. Following lines examplifies those configurations;

<error-page>
<exception-class>java.lang.Throwable</exception-class>
<location>/error/generalErrorPage.jsp</location>
</error-page>

<error-page>
<error-code>403</error-code>
<location>/error/accessDeniedPage.jsp</location>
</error-page>

Above lines are excerpts from a web.xml file. Those xml elements state that in case any uncaught exception occurs during request processing, request should be forwarded to defined location. We can be more specific in exception types in error-page definitions, so, for example, if we define another error page for java.lang.NullPointerException, an uncaught exception will be first checked against that definition, as it is more specific than java.langThrowable type. If we want to forward request to any other more specific error page, we can use errorPage directive as fallows; In customer.jsp: It is better to define isErrorPage=”true” attribute in generalErrorPage.jsp to able to access implicit exception variable. By the way, that exception information is kept in request with one of those two attributes, javax.servlet.jsp.jspException and javax.servlet.error.exception. Therefore, we can even access exception information without need of exception implicit variable. By the way, setting isErrorPage=”true” causes error forwarding not to work for jsf enabled java server pages. For JSF, above exception/error handling mechanism can be partly used, but we seek for a more complete solution to catch and handle exceptions. It would be better to extend FacesServlet and catch any exception, log and finally forward to a custom error page, but unfortunately this is not possible as FacesServlet is declared final. A detailed search on internet revealed that we could also extend default ActionListener and ViewHandler implementations and handle all exceptions while delegating necessary operations to their super type implementations respectively. We could, for example, extend default ActionListener implementation and provide an action processing method implementation similar to below;

public void processAction(ActionEvent event) {
    try {
        super.processAction(event);
    } catch (Exception e) {
        logger.error("Exception occured!",e);
        FacesContext context = FacesContext.getCurrentInstance();
        Context.getApplication().getNavigationHandler().handleNavigation(context, null, "error");
    }
}

then


  error
  /error.jsp

we also add a navigation rule like above into faces-config.xml, and don’t forget to define new action listener and view handlers as the system’s current handlers, again in faces-config.xml. And here comes a ViewHandler implementation sample;

try {
         super.renderView(context, viewToRender);
} catch (Exception e) {
         UIViewRoot errorViewRoot = createView(context, "/error.jsp");
         super.renderView(context, errorViewRoot);
}

Although we succeeded in making ActionListener implementation work as we expected, but view handler rendered an empty html page for error.jsp. I guess that we try to make faces servlet stop previous rendering process and start rendering error.jsp while not resetting faces servlet’s internal state back to a valid one. Another problem is that, we must most probably provide other custom handler or listener implementations for other faces parts, for example in validation handling. Our current solution employs aspects in order to surround FacesServlet’s service method with a try catch block. We catch any exception, log it and finally forward current request to custom error page. In order to do this, we used aspectj’s byte code weaving in jar feature.

Below is an excerpt from our aspect;

pointcut serviceMethod(ServletRequest request, ServletResponse response) :
	execution(public void FacesServlet.service(..)) && args(request,response);

void around(ServletRequest request, ServletResponse response) 
		throws IOException, ServletException : serviceMethod(request,response) {
	try {
		proceed(request,response);
	} catch(Exception e) {
		Logger.error("Exception!",e);
		Request.getRequestDispatcher("/error.jsp").forward(request,response);
	}
}

In conclusion, it is seen that jsf depends heavily on already existing error-page mechanism in handling uncaught exceptions for jsp pages, but this solution is far from complete, and we can say that it would be much better if java server faces had a general, one point configurable exception handling infrastructure, but it seems that at least for version 1.0 it is all over.